package per.example.arpproject.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.Blob;
import java.util.*;


/**
 * 公用工具类
 * 工具类要求:
 * 1.工具类方法一般为静态方法
 *
 * @author fs_wuhaixin
 * @date 2021-04-13
 */
@Slf4j
public class CommonUtil {

	/**
	 * 获得当前时间
	 * eg: return 20130816163200468 (yyyyMMddHHmmssSSS)
	 */
	public static String getCurDate() {
		return String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS%1$tL", new Date());
	}

	/**
	 * 判断是否是数字类型
	 */
	public static boolean isNum(String str, boolean whenNullReturnValue, boolean whenBackReturnValue) {
		if (str == null) {
			return whenNullReturnValue;
		} else {
			str = str.trim();
			if ("".equals(str)) {
				return whenNullReturnValue;
			} else {
				return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
			}
		}
	}

	public static boolean isNum(String str) {
		if (str == null || "".equals(str)) {
			return false;
		} else {
			return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");
		}
	}

	/**
	 * 判断基本类型的值是否在数组中 <in效果>(注意类型统一)
	 */
	public static boolean isInArray(Object obj, Object[] objs) {
		if (obj != null && objs != null && objs.length != 0) {
			for (Object arrObj : objs) {
				if (obj == arrObj || obj.equals(arrObj)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 返回首个不为空的的值
	 * 类似COALESCE方法
	 */
	public static Object coalesce(Object... objs) {
		if (objs != null && objs.length != 0) {
			for (int i = 0; i < objs.length; i++) {
				if (objs[i] != null && !"".equals(objs[i])) {
					return objs[i];
				}
			}
		}
		return null;
	}

	public static boolean isNotBlank(String str) {
		return StringUtils.isNotBlank(str);
	}

	public static boolean isBlank(String str) {
		return StringUtils.isBlank(str);
	}

	public static boolean isEmpty(String str) {
		return StringUtils.isEmpty(str);
	}

	public static boolean isNotEmpty(String str) {
		return StringUtils.isNotEmpty(str);
	}

	/**
	 * 生成32位的随机UUID,字母为大写
	 * @return
	 */
	public static String generatUuid() {
		return generatUuid(true);
	}

	/**
	 * 生成32位的随机UUID,字母为大写
	 * @return
	 */
	public static String generatUuid(boolean isUpperCase){
		if(isUpperCase){
			return UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
		}else{
			return UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");
		}
	}

	/**
	 * 取得访问来源的IP
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String unKnow = "unknown";
		String separator = ",";
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null || ip.length() == 0 || unKnow.equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
		}
		if (ip == null || ip.length() == 0 || unKnow.equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || unKnow.equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || unKnow.equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		// 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
		// "***.***.***.***".length()
		if (ip != null && ip.length() > 15) {
			if (ip.indexOf(separator) > 0) {
				ip = ip.substring(0, ip.indexOf(","));
			}
		}
		return ip;
	}

	/**
	 * 根据文件路径转换文件为字节流.
	 *
	 * @param filePath
	 * @return
	 */
	public static byte[] file2byte(String filePath) {
		byte[] buffer = null;
		try {
			File file = new File(filePath);
			buffer = file2byte(file);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return buffer;
	}

	/**
	 * 把文件转换为字节流
	 *
	 * @param file
	 * @return
	 */
	public static byte[] file2byte(File file) {
		byte[] buffer = null;
		try {
			FileInputStream fis = new FileInputStream(file);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int n;
			while ((n = fis.read(b)) != -1) {
				bos.write(b, 0, n);
			}
			fis.close();
			bos.close();
			buffer = bos.toByteArray();
		} catch (FileNotFoundException e) {
			log.error(e.getMessage(),e);
		} catch (IOException e) {
			log.error(e.getMessage(),e);
		}
		return buffer;
	}

	/**
	 * blob转字节流
	 *
	 * @param blob
	 * @return
	 */
	public static byte[] blobToBytes(Blob blob) {
		InputStream is = null;
		byte[] b = null;
		try {
			is = blob.getBinaryStream();
			b = new byte[(int) blob.length()];
			is.read(b);
			return b;
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		} finally {
			try {
				is.close();
				is = null;
			} catch (IOException e) {
				log.error(e.getMessage(),e);
			}
		}
		return b;
	}

	private static final char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

	/**
	 * 判断是否为MD5
	 *
	 * @param md5
	 * @return
	 */
	public static boolean isMd5(String md5) {
		int len = 32;
		if (md5.length() != len) {
			return false;
		}
		String upper = md5.toUpperCase();
		for (int i = 0; i < upper.length(); i++) {
			boolean res = false;
			for (char c : Digit) {
				if (c == upper.charAt(i)) {
					res = true;
				}
			}
			if (!res) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 获取本机网内地址
	 *
	 * @return
	 */
	public static InetAddress getInet4Address() {
		try {
			//获取所有网络接口
			Enumeration<NetworkInterface> allNetworkInterfaces = NetworkInterface.getNetworkInterfaces();
			//遍历所有网络接口
			while (allNetworkInterfaces.hasMoreElements()) {
				NetworkInterface networkInterface = allNetworkInterfaces.nextElement();
				//如果此网络接口为 回环接口 或者 虚拟接口(子接口) 或者 未启用 或者 描述中包含VM
				if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp() || networkInterface.getDisplayName().contains("VM") || networkInterface.getDisplayName().contains("VPN")) {
					//继续下次循环
					continue;
				}
				//遍历此接口下的所有IP（因为包括子网掩码各种信息）
				for (Enumeration<InetAddress> inetAddressEnumeration = networkInterface.getInetAddresses(); inetAddressEnumeration.hasMoreElements(); ) {
					InetAddress inetAddress = inetAddressEnumeration.nextElement();
					//如果此IP不为空
					if (inetAddress != null) {
						//如果此IP为IPV4 则返回
						if (inetAddress instanceof Inet4Address) {
							return inetAddress;
						}
					}
				}
			}
			return null;

		} catch (SocketException e) {
			log.error(e.getMessage(),e);
			return null;
		}
	}

	/**
	 * 获取IPV6地址.
	 * @return: java.net.InetAddress
	 * @Author: wuhx
	* @Date: 2021/8/6 10:09
	*/
	public static InetAddress getInet6Address() {
		InetAddress tempIn = null;
		try {
			//get all local ips
			Enumeration<NetworkInterface> interfs = NetworkInterface.getNetworkInterfaces();
			while (interfs.hasMoreElements()) {
				NetworkInterface interf = interfs.nextElement();
				Enumeration<InetAddress> addres = interf.getInetAddresses();
				while (addres.hasMoreElements()) {
					InetAddress in = addres.nextElement();
					if (in instanceof Inet6Address) {
						tempIn = in;
						break;
					}
				}
			}
		} catch (SocketException se) {
			log.error(se.getMessage(),se);
		}
		return tempIn;

	}

	/**
	 * 获取字符串的SHA256签名值
	 * @param str
	 * @return
	 */
	public static String getSha256Str(String str) {
		MessageDigest messageDigest;
		String encodeStr = "";
		try {
			messageDigest = MessageDigest.getInstance("SHA-256");
			messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
			encodeStr = byte2Hex(messageDigest.digest());
		} catch (NoSuchAlgorithmException e) {
			log.error(e.getMessage(),e);
		}
		return encodeStr;
	}

	/**
	 * 将byte转为16进制
	 * @param bytes
	 * @return
	 */
	private static String byte2Hex(byte[] bytes) {
		StringBuffer stringBuffer = new StringBuffer();
		String temp;
		for (byte arrbyte : bytes) {
			temp = Integer.toHexString(arrbyte & 0xFF);
			if (temp.length() == 1) {
				//1得到一位的进行补0操作
				stringBuffer.append("0");
			}
			stringBuffer.append(temp);
		}
		return stringBuffer.toString();
	}


	/**
	 * 将小写 key 转换为大写 key
	 *
	 * @param mapList 小写 key 的map
	 * @return 大写 keys 的map
	 */
	public static List<Map<String, String>> mapKeysToUpperCase(List<Map<String, Object>> mapList) {
		List<Map<String, String>> returnList = new ArrayList<>(mapList.size());
		mapList.forEach(map -> {
			Map<String, String> returnMap = new HashMap<>(map.size());
			map.forEach((key, val) -> {
				//null时转为“”
				val = val == null?"":val;
				// 转小写 key.toLowerCase()
				returnMap.put(key.toUpperCase(), String.valueOf(val));
			});
			returnList.add(returnMap);
		});
		return returnList;
	}
}
